package cn.niit.letuseatdemo.controller.store;
import cn.niit.letuseatdemo.entity.vo.response.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Controller
public class FileController {
    /** 上传文件的保存目录 */
    @Value("${fileutils.files.upload.path}")
    private String UPLOAD_PATH_FILE;
    @Value("${fileutils.files.upload.allowed.extensions}")
    private List<String> ALLOWED_EXTENSIONS_FILE;
    /** 上传图片的保存目录 */
    @Value("${fileutils.images.upload.path}")
    private String UPLOAD_PATH_IMAGE;
    @Value("${fileutils.images.upload.allowed.extensions}")
    private List<String> ALLOWED_EXTENSIONS_IMAGE;
    private static final String DOWNLOAD_IMAGE_PATH = "/download/image/";
    @GetMapping("/upload")
    public String index(){
        return "file";
    }
    /**
     * 通过<form></form> 表单的方式进行提交
     */
    @PostMapping("/upload/file")
    public String uploadFile(@RequestParam("file") MultipartFile file)
            throws IOException {
        if(file.isEmpty()){
            log.error("uploadFile == 上传的文件为空！");
            return "file";
        }
/** 校验文件的大小 */
        log.info("文件的大小是：{}", file.getSize());
/** 获取文件名 */
        String fileName = file.getOriginalFilename();
/** 获取文件类型（扩展名），并进行校验 */
        String suffixName = fileName.substring(fileName.lastIndexOf(".") +
                1);
        if(!isValidExtension(suffixName, ALLOWED_EXTENSIONS_FILE)){
            log.error("文件类{}不符合要求，请重新上传！", suffixName);
            return "file";
        }
/** 得到本地文件名（保存路径+文件名） */
        String filePath = UPLOAD_PATH_FILE + fileName;
/** 保存文件 */
        file.transferTo(new File(filePath));
        log.info("文件【{}】上传成功，保存为：{}", fileName, filePath);
        return "file";
    }
    /**
     * http://localhost:8088/download/file?fileName=泰山版.pdf
     * @return
     */
    @ResponseBody
    @GetMapping("/download/file")
    public BaseResponse<String> downloadFile(HttpServletRequest request,
                                             HttpServletResponse response, @RequestParam("fileName") String fileName){
/** 获取文件的完整路径 E:\\upload\\files\\泰山版.pdf */
        String filePath = UPLOAD_PATH_FILE + fileName;
        File file = new File(filePath);
        if(!file.exists()){
            return new BaseResponse("100001", "下载失败，文件不存在！");
        }
        try{
/** 响应头的内容类型 contentType TODO */
            ServletContext servletContext = request.getServletContext();
            String mimeType = servletContext.getMimeType(filePath);
            log.info("文件{}的MIME类型是：{}",fileName,mimeType);
            response.setContentType(mimeType);
//response.addHeader("Content�Disposition","attachment;filename=" + fileName);
// 文件名称如果为中文，会出现乱码
            response.addHeader("Content-Disposition","attachment;filename="
                    + URLEncoder.encode(fileName, "UTF-8"));
/** 下载文件 */
            FileCopyUtils.copyToByteArray(file);
            log.info("文件【{}】下载成功", fileName);
            return new BaseResponse("200", "下载成功，");
        }catch (Exception e){
            return new BaseResponse("100001", "下载失败，" + e.getMessage());
        }
    }
//================================ 以下是图片的上传、下载=======================
    /**
     * 图片上传
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/upload/image")
    @ResponseBody
    public Map<String, Object> uploadImage(@RequestParam("file")
                                                   MultipartFile file) throws IOException {
        Map<String, Object> result = new HashMap<>();
        if(file.isEmpty()){
            log.error("uploadFile == 上传的文件为空！");
            result.put("code", "10001");
            result.put("msg", "请求失败， 上传的文件为空");
            return result;
        }
        String fileName = file.getOriginalFilename();
/** 获取文件类型（扩展名），并进行校验 */
        String suffixName = fileName.substring(fileName.lastIndexOf(".") +
                1);
        if(!isValidExtension(suffixName, ALLOWED_EXTENSIONS_IMAGE)){
            log.error("文件类{}不符合要求，请重新上传！", suffixName);
            result.put("code", "10001");
            result.put("msg", "请求失败， 文件类不符合要求");
            return result;
        }
        File desc = new File(UPLOAD_PATH_IMAGE + fileName);
        file.transferTo(desc);
        result.put("code", "200");
        result.put("url", DOWNLOAD_IMAGE_PATH + fileName);
        result.put("msg", "上传成功");
        return result;
    }
    /**
     * 图片下载
     * @param fileName
     * @return
     */
// @GetMapping("/download/image/{filename}")
    public void downloadImage(
            HttpServletRequest request,
            HttpServletResponse response,
            @PathVariable("filename") String fileName) throws Exception {
        String filePath = UPLOAD_PATH_IMAGE + fileName;
        File file = new File(filePath);
        if(!file.exists()){
            throw new Exception("文件不存在！");
        }
        ServletContext servletContext = request.getServletContext();
        String mimeType = servletContext.getMimeType(filePath);
        log.info("文件{}的MIME类型是：{}",fileName,mimeType);
        response.reset();
        response.setContentType(mimeType);
        response.setContentLength((int)file.length());
        byte[] buffer = new byte[1024];
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        OutputStream os = null;
        try {
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            os = response.getOutputStream();
            int read = bis.read(buffer);
            while(read != -1){
                os.write(buffer, 0, read);
                read = bis.read(buffer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(null != bis){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null != fis){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /** 下载图片方式二 ：通过 FileCopyUtils */
    @GetMapping("/download/image/{filename}")
    public void downloadImage1(
            HttpServletRequest request,
            HttpServletResponse response,
            @PathVariable("filename") String fileName) throws Exception {
        String filePath = UPLOAD_PATH_IMAGE + fileName;
        File file = new File(filePath);
        if(!file.exists()){
            log.error("下载文件失败，文件【{}】不存在！",filePath);
            throw new Exception("文件不存在！");
        }
        ServletContext servletContext = request.getServletContext();
        String mimeType = servletContext.getMimeType(filePath);
        log.info("文件{}的MIME类型是：{}",fileName,mimeType);
        response.reset();
        response.setContentType(mimeType);
        response.setContentLength((int)file.length());
        byte[] buffer = FileCopyUtils.copyToByteArray(file);
        OutputStream os = response.getOutputStream();
        os.write(buffer);
    }
    /**
     * 验证上传的文件扩展名是否在允许范围内
     * @param extension 要上传的文件扩展名
     * @param extensions 允许上传的文件扩展名数组
     * @return
     */
    private boolean isValidExtension(String extension, List<String>
            extensions){
        for(String allowedExtension : extensions){
            if(extension.equalsIgnoreCase(allowedExtension)){
                return true;
            }
        }
        return false;
    }
    /**
     * 生成随机文件名
     * 此处自定义文件名,uuid + extension
     */
    private String getPathName(MultipartFile file) {
        String suffixName =
                file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf
                        (".") + 1);
        return UUID.randomUUID().toString() + "." + suffixName; //随机生成一个文件名
    }
}
